import { exec } from 'child_process'
import { join } from 'path'

import { noop } from 'lodash'
import { webpack } from 'webpack'
// @ts-expect-error
import WebpackDevServer from 'webpack-dev-server'

import { taskGroups } from '../cli/e2e-task-group'

import { getCompilers } from './cypress-compiler'

const { packageDir, rootDir } = require('./consts')

const distDir = join(rootDir, 'dist')

export function runCypress({ open, taskId }: { open?: boolean; parallel?: boolean; taskId?: string }) {
  const defer = {
    resolve: noop,
    reject: noop,
  }

  const pending = new Promise((resolve, reject) => {
    defer.resolve = resolve
    defer.reject = reject
  })

  const compiler = webpack(getCompilers(taskId))

  let started = false

  compiler.hooks.done.tap('done', () => {
    if (started) {
      return
    }
    started = true
    const cmd = open ? 'open' : 'run'
    const headlessFlag = open ? '' : '--headless'
    const spec = taskId ? `--spec ${taskGroups[taskId].testFiles.join(' ')}` : ''

    const cypressCommand = `${join(
      rootDir,
      'node_modules',
      '.bin',
      'cypress',
    )} ${cmd} ${headlessFlag} ${spec} --env IN_CI=${process.env.IN_CI ?? ''} --browser ${
      process.env.BROWSER ?? 'chromium'
    }`

    const { stdout, stderr } = exec(cypressCommand, {
      stdio: 'inherit',
      env: {
        ...process.env,
        TERM: 'xterm',
      },
    }).on('exit', (code) => {
      defer.resolve()
      process.exit(code!)
    })

    stdout?.pipe(process.stdout)
    stderr?.pipe(process.stderr)
  })

  const devServer = new WebpackDevServer(
    {
      hot: false,
      host: '0.0.0.0',
      client: false,
      liveReload: false,
      static: [
        {
          directory: distDir,
          watch: {
            ignored: /node_modules/,
          },
        },
        {
          directory: join(packageDir, 'slardar-lite'),
          watch: false,
        },
      ],
    },
    compiler,
  )

  return devServer.start().then(() => pending)
}
